#include<iostream>
#include<vector>
#include<fstream>
#include<assert.h>
#include<algorithm>
#include <string>


using namespace std;

class student
{
public:
	friend struct compare;
	student() = default;
	student(string Num,string name,char sex,size_t score)
		:_Num(Num),_name(name),_sex(sex),_score(score)
	{ }
	student(const student& s)
		:_Num(s._Num),_name(s._name),_sex(s._sex),_score(s._score)
	{ }
	void set(string Num, string name, char sex, size_t score)
	{
		_Num = Num;
		_name = name;
		_sex = sex;
		_score = score;
	}


	friend ostream& operator<<(ostream& out, const student& s);

	friend istream& operator>>(istream& in, student& s);

	bool operator>(const student& other) const 
	{
		return _score > other._score; 
	}

	bool writefile(const char* filename,int count) const
	{
		if (count == 0)
		{
			ofstream outfile(filename, ios::out); 
			if (outfile.is_open()) 
			{
				outfile << _Num << " " << _name << " " << _sex << " " << _score << endl;
				outfile.close();
			}
			else
			{
				return false;
			}
		}
		else
		{
			ofstream appendFile(filename, ios::app);
			if (appendFile.is_open()) 
			{
				appendFile << _Num << " " << _name << " " << _sex << " " << _score << endl;
				appendFile.close();
			}
			else
			{
				return false;
			}
		}
		return true;
	}

private:
	string _Num=" ";
	string _name=" ";
	char _sex=' ';
	size_t _score=0;
};

ostream& operator<<(ostream& out, const student& s)
{
	out << s._Num << " " << s._name << " " << s._sex << " " << s._score << endl;
	return out;
}

istream& operator>>(istream& in, student& s)
{
	in >> s._Num >> s._name >> s._sex >> s._score;
	return in;
}

struct compare
{
	bool operator() (const student& a, const student& b)
	{
		return (a._score < b._score);
	}
};



class studentcontrol
{
public:

	studentcontrol() = default;

	studentcontrol(vector<student>& vs)
		:_vs(vs){ }

	bool loadFromFile(const char* filename)
	{
		ifstream infile(filename);
		size_t i = 0;
		while (i < _vs.size())
		{
			if (infile.is_open())
			{
				string num;
				infile >> num;
				string name;
				infile >> name;
				char sex;
				infile >> sex;
				size_t score;
				infile >> score;
				_vs[i].set(num, name, sex, score);
				i++;
			}
			else
			{
				return false;
			}
		}
		infile.close();
		return true;
	}

	friend ostream& operator<<(ostream& out, studentcontrol& s);

	friend istream& operator>>(istream& in, studentcontrol& s);

	size_t size() const
	{
		return _vs.size();
	}

	student& operator[](size_t n)
	{
		assert(n < _vs.size());
		return _vs[n];
	}

	void sort()
	{
		std::sort(_vs.begin(), _vs.end(),compare());
	}

	bool writeToFile(const char* filename)
	{
		size_t i = 0;
		while (i < _vs.size())
		{
			_vs[i].writefile(filename,i);
		    i++;
		}
		return true;
	}

	~studentcontrol(){}
private:
	vector<student> _vs;
};

ostream& operator<<(ostream& out, studentcontrol& s)
{
	for (size_t i = 0; i < s.size(); i++)
	{
		out << s[i] << endl;
	}
	return out;
}

istream& operator>>(istream& in, studentcontrol& s)
{
	for (size_t i = 0; i < s.size(); i++)
	{
		in >> s[i];
	}
	return in;
}

void testStudentAndStudentControl()
{

	student s1("1001", "Alice", 'F', 85);
	student s2("1002", "Bob", 'M', 92);
	student s3("1003", "Charlie", 'M', 78);
	student s4("1004", "Diana", 'F', 88);

	vector<student> students = { s1, s2, s3, s4 };
	studentcontrol sc(students);


	sc.sort();
	cout << "After sorting:" << endl;
	cout << sc;

	const char* filename = "students.txt";
	if (sc.writeToFile(filename))
	{
		cout << "Write to file successfully." << endl;
	}
	else
	{
		cerr << "Failed to write to file." << endl;
		return;
	}


	vector<student> newStudents(4);
	studentcontrol newSc(newStudents);
	if (newSc.loadFromFile(filename))
	{
		cout << "Load from file successfully." << endl;
		cout << newSc;
	}
	else
	{
		cerr << "Failed to load from file." << endl;
		return;
	}


	if (s1.writefile("student1.txt",0))
	{
		cout << "Write single student to file successfully." << endl;
	}
	else
	{
		cerr << "Failed to write single student to file." << endl;
	}

	student s5;
	cout << "Enter student information (Num name sex score): ";
	cin >> s5;
	cout << "You entered: " << s5;
}

int main()
{
	testStudentAndStudentControl();
	return 0;
}